POJ2823 Sliding Window

经典滑动窗口求最值问题
紫书P241


思想

利用了min/max,充分利用区间的信息,实现优化。

实现

用一个双端队列(数组/deque),里面存放有效的指针(数组下标)信息

求所有子区间min

原理:假如窗口中有1,2元素且2在1左边,那么这个2是无用信息,应当删除(从队列中删除)

求所有子区间max

原理:与求min相反


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<cstdio>
#define inf 1<<30
int a[1000001],n,m,q[1000001], ansmin[1000001], ansmax[1000001];

void findmin()
{
int st=1, ed=0;
for(int i=1;i<=n;i++)
{
while(ed >= st && a[i] < a[q[ed]])
--ed;
q[++ed]=i;
while(ed >= st && q[st]<=i-m)
++st;
if(i>=m) ansmin[i-m+1]=a[q[st]];
}
}

void findmax()
{
int st=1, ed=0;
for(int i=1;i<=n;i++)
{
while(ed >= st && a[i] > a[q[ed]])
--ed;
q[++ed]=i;
while(ed >= st && q[st]<=i-m)
++st;
if(i>=m) ansmax[i-m+1]=a[q[st]];
}
}

int main()
{
scanf("%d%d", &n, &m);
for(int i=1;i<=n;i++)
scanf("%d", &a[i]);
findmax();
findmin();
for(int i=1;i<=n-m+1;i++)
printf("%d%c", ansmin[i], i==n-m+1?'\n':' ');
for(int i=1;i<=n-m+1;i++)
printf("%d%c", ansmax[i], i==n-m+1?'\n':' ');
}